package vg.shared.exporters;

import java.util.Collection;
import java.util.Map;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import vg.services.data_base_manager.data.graph.Attribute;
import vg.services.data_base_manager.data.graph.Edge;
import vg.services.data_base_manager.data.graph.Graph;
import vg.services.data_base_manager.data.graph.Vertex;
import vg.services.main_manager.MainManager;

public class GraphMLExporter {
	public static void saveGraphML(String absoluteFileName, int graphModelId) {
        // TODO FIX ME
        throw new NotImplementedException();
//
//        FileOutputStream out = null;
//		try {
//			DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
//			DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
//
//			// root elements
//			Document doc = docBuilder.newDocument();
//			Element rootElement = doc.createElement("graphml");
//			rootElement.setAttribute("xmlns", "http://graphml.graphdrawing.org/xmlns");
//			rootElement.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
//			rootElement.setAttribute("xsi:schemaLocation", "http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd");
//			doc.appendChild(rootElement);
//
//			// save keys
//			Map<String, Class<?>> vertices_attr = MainManager.graphDataBase.getVertexAttributes4GraphModel(graphModelId);
//			Map<String, Class<?>> edges_attr = MainManager.graphDataBase.getEdgeAttributes4GraphModel(graphModelId);
//
//			for (String buf : vertices_attr.keySet()) {
//				Class<?> type = vertices_attr.get(buf);
//				Element key_node = doc.createElement("key");
//				key_node.setAttribute("id", "node_" + buf);
//				key_node.setAttribute("for", "node");
//				key_node.setAttribute("attr.name", buf);
//				key_node.setAttribute("attr.type", DataBaseTypeParser.class2string(type));
//				rootElement.appendChild(key_node);
//			}
//
//			for (String buf : edges_attr.keySet()) {
//				Class<?> type = edges_attr.get(buf);
//				Element key_node = doc.createElement("key");
//				key_node.setAttribute("id", "edge_" + buf);
//				key_node.setAttribute("for", "edge");
//				key_node.setAttribute("attr.name", buf);
//				key_node.setAttribute("attr.type", DataBaseTypeParser.class2string(type));
//				rootElement.appendChild(key_node);
//			}
//
//			//graph_traverse(doc, rootElement, MainManager.graphDataBase.getAllRootGraphIds(graphModelId), vertices_attr, edges_attr);
//
//			// write the content into xml file
//			OutputFormat format = new OutputFormat(doc);
//			format.setIndenting(true);
//
//			// to generate a file output use fileoutputstream instead of decoders.out
//			out = new FileOutputStream(new File(absoluteFileName));
//			XMLSerializer serializer = new XMLSerializer(out, format);
//			serializer.serialize(doc);
//		} catch (Exception ex) {
//			MainManager.windowMessage.showExceptionMessage(ex);
//		} finally {
//			try {
//				if (out != null)
//					out.close();
//			} catch (Exception ex) {
//				MainManager.logger.printException(ex);
//			}
//		}
	}

//=============================================================================
//-----------------PRIVATE METHODS---------------------------------------------	
	private static void graph_traverse(Document doc, Element root, Graph graph, Map<String, Class<?>> vertices_attr, Map<String, Class<?>> edges_attr) {
		if (graph == null || graph.isEmpty()) return;
		
		// save graph info
		Element graph_node = doc.createElement("graph");
		graph_node.setAttribute("id", "graph_" + Integer.toString(graph.getStorableId()));
		if (graph.isDirected())
			graph_node.setAttribute("edgedefault", "directed");
		else
			graph_node.setAttribute("edgedefault", "undirected");
		root.appendChild(graph_node);
		
		root = graph_node;
		
		Collection<Vertex> vertices = graph.getVertices();
		Collection<Edge> edges = graph.getEdges();
		
		// save vertex
		if (vertices != null && vertices.size() > 0) {
			for (Vertex buf : vertices) {
				Element node = doc.createElement("node");
				node.setAttribute("id", "v_" + buf.getStorableId());
				root.appendChild(node);
				vertex_traverse(doc, node, buf, vertices_attr);
				if (buf.isInnerGraph()) {
					Graph innerGraph = MainManager.graphDataBase.getGraph(buf.getInnerGraphId());
					graph_traverse(doc, node, innerGraph, vertices_attr, edges_attr);
				}
			}
		} 

		// save edge
		if (edges != null && edges.size() > 0) {
			for (Edge buf : edges) {
				Element node = doc.createElement("edge");
				node.setAttribute("id", "e_" + buf.getStorableId());
				node.setAttribute("source", "v_" + buf.getSource().getStorableId());
				node.setAttribute("target", "v_" + buf.getTarget().getStorableId());
				root.appendChild(node);
				edge_traverse(doc, node, buf, edges_attr);
			}
		}
	}
	
	private static void vertex_traverse(Document doc, Element root, Vertex vertex, Map<String, Class<?>> vertices_attr) {
		if (vertex == null || vertex.isEmpty()) return;
		
		for (Attribute buf : vertex.getAttributes()) {
			String name = buf.getName();
			if (name == null || name.length() == 0 || !vertices_attr.containsKey(name)) continue;
			
			Element data_node = doc.createElement("data");
			data_node.setAttribute("key", "node_" + name);
			data_node.appendChild(doc.createTextNode(buf.toNotNullStringValue()));
			root.appendChild(data_node);
		}
	}

	private static void edge_traverse(Document doc, Element root, Edge edge, Map<String, Class<?>> edges_attr) {
		if (edge == null || edge.isEmpty()) return;
		
		for (Attribute buf : edge.getAttributes()) {
			String name = buf.getName();
			if (name == null || name.length() == 0 || !edges_attr.containsKey(name)) continue;
			
			Element data_node = doc.createElement("data");
			data_node.setAttribute("key", "edge_" + name);
			data_node.appendChild(doc.createTextNode(buf.toNotNullStringValue()));
			root.appendChild(data_node);
		}
	}
}
